#!/usr/bin/perl
use Net::SMTP;

#Constants
my $BZR_ROOT   = '/usr/local/bzrroot/';
my $TO_EMAIL   = 'sourcechanges@YOURDOMAIN.com';
my $FROM_EMAIL = 'commits@YOURDOMAIN.com';
my $SENDMAIL   = "/usr/sbin/sendmail -t";
my $DIR        = "/usr/share/bzr-email-notifier";

#Global variables
%last_rev;
my %current;
my $changes;

#Code
&checkFirstRun;
while (true) {
    &doLoop;
    sleep(600);
}

#Subroutines
sub doLoop {
    `sh makestate.sh $BZR_ROOT`;
    &config('state', \%last_rev);
    &config('current', \%current);
    `rm $DIR/current`;
    &findChanges($BZR_ROOT);
    &saveState;
}

sub checkFirstRun {
    open  (STATE, "state") or do {`sh makestate.sh $BZR_ROOT;cp $DIR/current $DIR/state`;};
    close(STATE);
}

sub findChanges {
    #either: 
    # 1. it's a new branch
    # 2. it's an old branch and has changed
    # 3. it's an old branch and has not changed
    for (keys %current) {
	if (!$last_rev{$_}) {
	    &newBranch($_);
	} elsif ($last_rev{$_} != $current{$_}) {
	    $changes = `bzr log $_ -vpr $last_rev{$_}..$current{$_}`;
	    &changedBranch($_, $changes);
	} #else it hasn't changed
    }
}

sub changedBranch {
    $branch = $_[0];
    $branch =~ s/$BZR_ROOT//;

    &sendMail("Commit Revision" . ($current{$_}==$last_rev{$_}+1 ? " $current{$_}" : "s " . ($last_rev{$_}+1) . " to $current{$_}") . " in branch \"$branch\"", "$changes");
}

sub newBranch {
    $branch = $_[0];
    $branch =~ s/$BZR_ROOT//;
    $by = `cat $_[0]/.bzr/branch/last-revision | awk '{print \$2}'`;
    $by =~ s/-.*?$//;

    &sendMail("New Branch Created - \"$branch\"", "Branch \"$branch\" was created by $by\n");
}

sub sendMail {
    #print "To: $TO_EMAIL\nFrom:$FROM_EMAIL\nSubject:$_[0]\nBODY:$_[1]\n";
    $smtp = Net::SMTP->new('localhost');
    $smtp->mail($FROM_EMAIL);
    $smtp->to($TO_EMAIL);
    $smtp->data();
    $smtp->datasend("To: $TO_EMAIL\n");
    $smtp->datasend("Subject: $_[0]");
    $smtp->datasend("\n");
    $smtp->datasend("$_[1]\n");
    $smtp->dataend();
    $smtp->quit;
}

sub saveState {
    `mv $DIR/state $DIR/state.bck`;
    for (keys %current) {
	open (STATE, ">>$DIR/state");
	print STATE "$_\n$current{$_}\n";
	close(STATE);
    }
}

sub config {
    open (STATE, "$DIR/$_[0]");
    my @state = <STATE>;
    for (my $i = 0; $i < @state; $i += 2) {
	chomp($state[$i]);
	chomp($state[$i+1]);
	$_[1]{$state[$i]} = $state[$i+1];
    }
    close(STATE);
}
